home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 3 / Gold Medal Software - Volume 3 (Gold Medal) (1994).iso / graphics / 3dvect30.arj / MATH.INC < prev    next >
Text File  |  1993-11-18  |  55KB  |  2,201 lines

  1. ; math.inc - general math functions.
  2.  
  3.            public rotate        ; rotate using vmatrix
  4.            public rotatenull    ; 16 bit rotate by ematrix
  5.            public make3d        ; calculate 3d ?actual*?/z ( both x and y)
  6.            public make3dx       ; xactual*x/z
  7.            public make3dy       ; yactual*y/z
  8.            public erotate       ; 32 bit rotate using ematrix
  9.            public zsolve        ; solve single equation variable
  10.            public ysolve
  11.            public xsolve
  12.            public cosign
  13.            public sign
  14.            public arctan
  15.            public compound      ; generate rotation matrix (includes camera)
  16.            public setsincose
  17.            public temp_matrix
  18.            public matrix_multiply
  19.  
  20.            public set_precal7
  21.            public set_precal147
  22.            public frotate
  23.            public z16x
  24.            public z16z
  25.  
  26.            public fzsolve
  27.            public fxsolve
  28.            public fysolve
  29.  
  30.            public precal1
  31.            public precal4
  32.            public precal7
  33.  
  34.            public sqrt          ; eax=sqr(eax), thanks to TRAN!
  35.            public sqrax2bx2     ; ax = sqr(ax^2+bx^2)
  36.  
  37.            public pre_cal_lambert   ; scan object si and calculate surface normals
  38.            public calc_normal       ; guess...from 3 points, returns vector ebx,ecx,ebp
  39.            public lambert           ; calculate surface normal rotation matrix for object si
  40.            public set_up_all_lambert; scans objects from si to di and calls pre_cal_lambert
  41.            public lrotate           ; given normal for surface, figures out intensity
  42.  
  43.            public lx1               ; points to load up before calling calc_normal
  44.            public ly1
  45.            public lz1
  46.            public lx2
  47.            public ly2
  48.            public lz2
  49.            public lx3
  50.            public ly3
  51.            public lz3
  52.  
  53. ; point rotation is 16 bit and uses vmatrix
  54. ; camera rotation is 32 bit and uses ematrix
  55. ; frotate uses rotation along a plane and uses ematrix with precal147
  56.  
  57. ; point rotation
  58. ; bx = x   cx = y   bp = z    16 bit rotation!
  59. ; clobbers dx,si,ax
  60.  
  61. ; remember , matrix offsets are:
  62. ;
  63. ;  0 1 2     multiply those by 4 four the doublewords
  64. ;  3 4 5
  65. ;  6 7 8
  66. ;
  67.            align 16
  68.  
  69. rotate:
  70.            mov ax,vmatrix+4    ; solve x = bx(0)+cx(1)+bp(2)
  71.            imul bp
  72.            shrd ax,dx,14
  73.            movsx edi,ax
  74.            mov ax,vmatrix+2
  75.            imul cx
  76.            shrd ax,dx,14
  77.            movsx eax,ax
  78.            add edi,eax
  79.            mov ax,vmatrix+0
  80.            imul bx
  81.            shrd ax,dx,14
  82.            movsx eax,ax
  83.            add edi,eax   ; di = new x
  84.  
  85.            mov ax,vmatrix+10   ; solve y = bx(3)+cx(4)+bp(5)
  86.            imul bp
  87.            shrd ax,dx,14
  88.            movsx esi,ax
  89.            mov ax,vmatrix+8
  90.            imul cx
  91.            shrd ax,dx,14
  92.            movsx eax,ax
  93.            add esi,eax
  94.            mov ax,vmatrix+6
  95.            imul bx
  96.            shrd ax,dx,14
  97.            movsx eax,ax
  98.            add esi,eax   ; si = new y
  99.  
  100.            mov ax,vmatrix+16   ; solve z = bx(6)+cx(7)+bp(8)
  101.            imul bp
  102.            shrd ax,dx,14
  103.            movsx ebp,ax
  104.            mov ax,vmatrix+14
  105.            imul cx
  106.            shrd ax,dx,14
  107.            movsx eax,ax
  108.            add ebp,eax
  109.            mov ax,vmatrix+12
  110.            imul bx
  111.            shrd ax,dx,14
  112.            movsx eax,ax
  113.            add ebp,eax   ; bp = new z
  114.  
  115.            mov ecx,esi
  116.            mov ebx,edi
  117.  
  118.            ret
  119.  
  120. ; 16 bit rotate by ematrix - used when objects have no rotation/constant angle
  121.  
  122.            align 16
  123.  
  124. rotatenull:
  125.            mov ax,w ematrix+4*2   ; solve x = bx(0)+cx(1)+bp(2)
  126.            imul bp
  127.            shrd ax,dx,14
  128.            movsx edi,ax
  129.            mov ax,w ematrix+2*2
  130.            imul cx
  131.            shrd ax,dx,14
  132.            movsx eax,ax
  133.            add edi,eax
  134.            mov ax,w ematrix+0*2
  135.            imul bx
  136.            shrd ax,dx,14
  137.            movsx eax,ax
  138.            add edi,eax   ; di = new x
  139.  
  140.            mov ax,w ematrix+10*2   ; solve y = bx(3)+cx(4)+bp(5)
  141.            imul bp
  142.            shrd ax,dx,14
  143.            movsx esi,ax
  144.            mov ax,w ematrix+8*2
  145.            imul cx
  146.            shrd ax,dx,14
  147.            movsx eax,ax
  148.            add esi,eax
  149.            mov ax,w ematrix+6*2
  150.            imul bx
  151.            shrd ax,dx,14
  152.            movsx eax,ax
  153.            add esi,eax   ; si = new y
  154.  
  155.            mov ax,w ematrix+16*2   ; solve z = bx(6)+cx(7)+bp(8)
  156.            imul bp
  157.            shrd ax,dx,14
  158.            movsx ebp,ax
  159.            mov ax,w ematrix+14*2
  160.            imul cx
  161.            shrd ax,dx,14
  162.            movsx eax,ax
  163.            add ebp,eax
  164.            mov ax,w ematrix+12*2
  165.            imul bx
  166.            shrd ax,dx,14
  167.            movsx eax,ax
  168.            add ebp,eax   ; bp = new z
  169.  
  170.            mov ecx,esi
  171.            mov ebx,edi
  172.  
  173.            ret
  174.  
  175.            align 16
  176.  
  177. ; fast ratiox and ratioy are 320x and 464y
  178. ; multiplication has been substituted with fast lea
  179.  
  180. ; trashes eax,edx,edi
  181.  
  182. make3d:                            ; bp must always be positive
  183.            cmul eax,ebx,ratiox     ; use fast constant multiply
  184.  
  185.            idiv ebp
  186.            mov ebx,eax
  187. make3dy:
  188.            cmul eax,ecx,ratioy
  189.  
  190.            idiv ebp
  191.            mov ecx,eax
  192.  
  193.            ret
  194.  
  195. make3dx:                           ; bp must always be positive
  196.            cmul eax,edi,ratiox
  197.  
  198.            idiv esi
  199.            mov edi,eax
  200.  
  201.            ret
  202.  
  203. ; checks if a side is visible.
  204. ; DI, SI, DX = x's
  205. ; BP, DS, ES = y's
  206. ; return: cx register...
  207. ; cx > 0: side visible...else not...routine courtesy of "RAZOR"
  208. ; eg:
  209. ;          call checkfront
  210. ;          cmp cx,0
  211. ;          jng dontdraw
  212.  
  213.            align 16
  214.  
  215. checkfront:
  216.            cmp di,si
  217.            jng s cfc2
  218.            mov ax,di
  219.            mov di,si
  220.            mov si,dx
  221.            mov dx,ax
  222.            mov ax,bp
  223.            mov bp,dsq
  224.            mov bx,esq
  225.            mov dsq,bx
  226.            mov esq,ax
  227. cfc:
  228.            cmp di,si
  229.            jng s cfc2
  230.            mov ax,di
  231.            mov di,si
  232.            mov si,dx
  233.            mov dx,ax
  234.            mov ax,bp
  235.            mov bp,dsq
  236.            mov bx,esq
  237.            mov dsq,bx
  238.            mov esq,ax
  239. cfc2:
  240.            mov ax,dx                 ; ax = x3
  241.            sub ax,di                 ; ax = x3 - x1
  242.            mov bx,dsq                ; bx = y2
  243.            sub bx,bp                 ; bx = y2 - y1
  244.            movsx eax,ax              ; modification to allow large checks
  245.            movsx ebx,bx
  246.            imul ebx                  ; ax = (x3-x1)*(y2-y1)
  247.            mov ecx,eax               ; save it...
  248.            mov ax,si                 ; ax = x2
  249.            sub ax,di                 ; ax = x2 - x1
  250.            mov bx,esq                ; bx = y3
  251.            sub bx,bp                 ; bx = y3 - y1
  252.            movsx eax,ax
  253.            movsx ebx,bx
  254.            imul ebx                  ; ax = (x2-x1)*(y3-y1)
  255.            sub ecx,eax               ; cx = (x3-x1)*(y2-y1)-(x2-x1)*(y3-y1)
  256.            ret
  257.  
  258. ; point rotation for eye - solves all x,y,z parameters
  259. ; ebx = x   ecx = y   ebp = z   32 bit rotation!
  260. ; clobbers dx,si,di,ax
  261.  
  262.            align 16
  263.  
  264. erotate:
  265.            mov eax,ematrix+8
  266.            imul ebp
  267.            shrd eax,edx,14
  268.            mov edi,eax
  269.            if usez eq yes
  270.            mov eax,ematrix+4
  271.            imul ecx
  272.            shrd eax,edx,14
  273.            add edi,eax
  274.            endif
  275.            mov eax,ematrix+0
  276.            imul ebx
  277.            shrd eax,edx,14
  278.            add edi,eax   ; di = new x
  279.  
  280.            mov eax,ematrix+20
  281.            imul ebp
  282.            shrd eax,edx,14
  283.            mov esi,eax
  284.            mov eax,ematrix+16
  285.            imul ecx
  286.            shrd eax,edx,14
  287.            add esi,eax
  288.            mov eax,ematrix+12
  289.            imul ebx
  290.            shrd eax,edx,14
  291.            add esi,eax   ; si = new y
  292.  
  293.            mov eax,ematrix+32
  294.            imul ebp
  295.            shrd eax,edx,14
  296.            mov ebp,eax
  297.            mov eax,ematrix+28
  298.            imul ecx
  299.            shrd eax,edx,14
  300.            add ebp,eax
  301.            mov eax,ematrix+24
  302.            imul ebx
  303.            shrd eax,edx,14
  304.            add ebp,eax   ; bp = new z
  305.  
  306.            mov ecx,esi
  307.            mov ebx,edi
  308.  
  309.            ret
  310.  
  311. ; solve z from ematrix - same as above erotate but only solves z for fast
  312. ; test of where object is - result is in esi
  313.  
  314.            align 16
  315.  
  316. zsolve:
  317.            mov eax,ematrix+32
  318.            imul ebp
  319.            shrd eax,edx,14
  320.            mov esi,eax
  321.            mov eax,ematrix+28
  322.            imul ecx
  323.            shrd eax,edx,14
  324.            add esi,eax
  325.            mov eax,ematrix+24
  326.            imul ebx
  327.            shrd eax,edx,14
  328.            add esi,eax   ; si = new z
  329.            ret
  330.  
  331. ; if object z test from above routine is positive, this routine will solve
  332. ; the rest of the rotation matrix.  this is so we don't waste time solving
  333. ; for x and y locations if the object is not within screen parameters.
  334. ; saves imuls
  335.  
  336.            align 16
  337. xsolve:
  338.            mov eax,ematrix+8
  339.            imul ebp
  340.            shrd eax,edx,14
  341.            mov edi,eax
  342.            if usez eq yes
  343.            mov eax,ematrix+4
  344.            imul ecx
  345.            shrd eax,edx,14
  346.            add edi,eax
  347.            endif
  348.            mov eax,ematrix+0
  349.            imul ebx
  350.            shrd eax,edx,14
  351.            add edi,eax   ; di = new x
  352.            ret
  353.  
  354.            align 16
  355. ysolve:
  356.            mov eax,ematrix+16
  357.            imul ecx
  358.            shrd eax,edx,14
  359.            mov ecx,eax
  360.            mov eax,ematrix+12
  361.            imul ebx
  362.            shrd eax,edx,14
  363.            add ecx,eax
  364.            mov eax,ematrix+20
  365.            imul ebp
  366.            shrd eax,edx,14
  367.            add ecx,eax   ; cx = new y
  368.  
  369.            mov ebx,edi   ; final test, move into appropriate regs
  370.            mov ebp,esi
  371.  
  372.            ret
  373.  
  374. ; calculate sign into eax, from ax, smashes bx
  375. ; after imul by sign, shr eax,14 to compensate for decimal factor!
  376.  
  377.            align 16
  378.  
  379. cosign:
  380.            add ax,4000h
  381. sign:
  382.            shr ax,2
  383.            cmp ax,2000h
  384.            jge s q3o4         ; quadrant 3 or 4
  385.  
  386.            cmp ax,1000h
  387.            jl s q0            ; quad 1
  388.  
  389.            mov ebx,1fffh
  390.            sub bx,ax
  391.            jmp s halfsign     ; quad 2
  392. q0:
  393.            movzx ebx,ax
  394.            jmp s halfsign
  395. q3o4:
  396.            cmp ax,3000h
  397.            jl s q3
  398.            mov ebx,3fffh
  399.            sub bx,ax
  400.            call halfsign      ; quad 4
  401.            neg eax
  402.            ret
  403. q3:
  404.            and ax,0fffh
  405.            movzx ebx,ax       ; quad 3
  406.            call halfsign
  407.            neg eax
  408.            ret
  409. halfsign:
  410.            movzx eax,w sinus[ebx*2]
  411.            ret
  412.  
  413. ; arctan, ecx=rise,eax=run, returns ax as angle of triangle
  414. ; smashes cx,ax,dx,si
  415.  
  416.            align 16
  417.  
  418. arctan:
  419.            cmp eax,0
  420.            jl s qd2or3
  421.            cmp ecx,0
  422.            jge s halftax      ; quadrant 1
  423.            neg ecx            ; quadrant 4, ax=-ax
  424.            call halftan
  425.            neg ax
  426.            shl ax,2
  427.            ret
  428. qd2or3:
  429.            neg eax
  430.            cmp ecx,0
  431.            jge s qd2
  432.            neg ecx            ; quad 3, ax=ax+8192
  433.            call halftan
  434.            add ax,8192
  435.            shl ax,2
  436.            ret
  437. qd2:
  438.            call halftan
  439.            neg ax
  440.            add ax,8192
  441.            shl ax,2
  442.            ret
  443. halftax:
  444.            call halftan
  445.            shl ax,2
  446.            ret
  447.  
  448.            align 16
  449.  
  450. halftan:
  451.            xor edx,edx
  452.  
  453. ; cx=rise  positive
  454. ; ax=run   positive
  455.  
  456.            cmp eax,ecx
  457.            jl s opptan        ; greater than 45 degrees, other side...
  458.  
  459.            xchg ecx,eax       ; ax<cx
  460.            shld edx,eax,11    ; *2048 edx = high dword for divide
  461.            shl eax,11         ; *2048
  462.            div ecx
  463.            movzx esi,ax
  464.            mov ax,w negtan[esi*2] ; resulting angle (0-512 is 0-45) in ax
  465.            ret
  466.  
  467.            align 16
  468.  
  469. opptan:
  470.            shld edx,eax,11    ; *2048 edx = high dword for divide
  471.            shl eax,11         ; *2048
  472.  
  473.            div ecx
  474.            movzx esi,ax       ; ax remainder
  475.            mov cx,w negtan[esi*2]
  476.            mov ax,1000h
  477.            sub ax,cx          ; resulting angle (2048-4096 is 45-90) in ax
  478.            ret
  479.  
  480.            align 16
  481.  
  482. ; generate object matrix, 12 imul's first
  483.  
  484. ;              x                         y                      z
  485. ;
  486. ;x=  cz * cy - sx * sy * sz   - sz * cy - sx * sy * cz     - cx * sy
  487. ;
  488. ;y=         sz * cx                   cx * cz                - sx
  489. ;
  490. ;z=  cz * sy + sx * sz * cy   - sy * sz + sx * cy * cz       cx * cy
  491. ;
  492. ;then perform matrix multiply by negative x and z matricies
  493. ;
  494. ; -x matrix                             -z matrix
  495. ;     x       y       z                   x       y       z
  496. ;
  497. ;x    1       0       0                cz     sz       0
  498. ;
  499. ;y    0      cx       sx              -sz     cz       0
  500. ;
  501. ;z    0     -sx       cx                0      0       1
  502. ;
  503. ; notice original object matrix takes 12 imuls, camera modify takes 24, can
  504. ; you do this faster? (less imuls)
  505.  
  506. compound:
  507.            push esi
  508.  
  509.            mov ax,vxs[esi*2]
  510.            neg ax
  511.            push ax
  512.            call cosign
  513.            mov vcosx,ax
  514.            pop ax
  515.            call sign
  516.            mov vsinx,ax
  517.            mov ebp,eax            ; bp = sx
  518.            neg ax
  519.            mov [vmatrix+10],ax
  520.  
  521.            mov ax,vzs[esi*2]
  522.            neg ax
  523.            push ax
  524.            call cosign
  525.            mov vcosz,ax
  526.            mov edi,eax            ; di = cz
  527.            pop ax
  528.            call sign
  529.            mov vsinz,ax
  530.            mov edx,eax            ; dx = sz
  531.  
  532.            mov ax,vys[esi*2]
  533.            neg ax
  534.            add ax,eyeay
  535.            push ax
  536.            call cosign
  537.            mov vcosy,ax
  538.            pop ax
  539.            call sign
  540.            mov vsiny,ax           ; ax = sy
  541.  
  542.            mov bx,dx              ; save sz
  543.  
  544.            mov cx,ax              ; save sy
  545.  
  546.            imul bx                ; bx = - sy * sz
  547.            shrd ax,dx,14
  548.            movsx ebx,ax
  549.            neg bx
  550.            mov [vmatrix+14],bx
  551.  
  552.            mov ax,cx              ; si = cz * sy
  553.            imul di
  554.            shrd ax,dx,14
  555.            mov si,ax
  556.            mov [vmatrix+12],si
  557.  
  558.            mov ax,vcosy
  559.  
  560.            imul di                ; di = cy * cz
  561.            shrd ax,dx,14
  562.            mov di,ax
  563.            mov [vmatrix+0],di
  564.  
  565.            mov ax,vsinz
  566.            mov cx,vcosy
  567.  
  568.            imul cx                ; cx = - sz * cy
  569.            shrd ax,dx,14
  570.            mov cx,ax
  571.            neg cx
  572.            mov [vmatrix+2],cx
  573.  
  574.            mov ax,bp
  575.            imul si
  576.            shrd ax,dx,14
  577.            mov si,ax
  578.            neg esi
  579.            add [vmatrix+2],si
  580.  
  581.            mov ax,bp
  582.            imul di
  583.            shrd ax,dx,14
  584.            mov di,ax
  585.            add [vmatrix+14],di
  586.  
  587.            mov ax,bp
  588.            imul bx
  589.            shrd ax,dx,14
  590.            mov bx,ax
  591.            add [vmatrix+0],bx
  592.  
  593.            mov ax,bp
  594.            imul cx
  595.            shrd ax,dx,14
  596.            mov cx,ax
  597.            neg cx
  598.            add [vmatrix+12],cx
  599.  
  600.            mov si,vcosx
  601.  
  602.            mov ax,vcosy
  603.            imul si                   ; cx * cy
  604.            shrd ax,dx,14
  605.            mov [vmatrix+16],ax
  606.  
  607.            mov ax,vsiny
  608.            imul si                   ;-cx * sy
  609.            shrd ax,dx,14
  610.            neg ax
  611.            mov [vmatrix+4],ax
  612.  
  613.            mov ax,vsinz
  614.            imul si                    ; cx * sz
  615.            shrd ax,dx,14
  616.            mov [vmatrix+6],ax
  617.  
  618.            mov ax,vcosz
  619.            imul si                    ; cx * cz
  620.            shrd ax,dx,14
  621.            mov [vmatrix+8],ax
  622.  
  623.            mov edi,ecosx              ; now perform camera x rotation,12 imuls
  624.            mov esi,esinx
  625.            mov ebp,esi
  626.            neg ebp
  627.  
  628.            mov ax,[vmatrix+6]
  629.            imul di
  630.            shrd ax,dx,14
  631.            mov cx,ax
  632.  
  633.            mov ax,[vmatrix+12]
  634.            imul si
  635.            shrd ax,dx,14
  636.  
  637.            add ecx,eax                ; ecx = new vmatrix+12
  638.  
  639.            mov ax,[vmatrix+6]
  640.            imul bp
  641.            shrd ax,dx,14
  642.            mov bx,ax
  643.  
  644.            mov ax,[vmatrix+12]
  645.            imul di
  646.            shrd ax,dx,14
  647.  
  648.            add ebx,eax                ; ebx = new vmatrix+24
  649.  
  650.            mov [vmatrix+6],cx
  651.            mov [vmatrix+12],bx
  652.  
  653.            mov ax,[vmatrix+8]
  654.            imul di
  655.            shrd ax,dx,14
  656.            mov cx,ax
  657.  
  658.            mov ax,[vmatrix+14]
  659.            imul si
  660.            shrd ax,dx,14
  661.  
  662.            add cx,ax                ; ecx = new vmatrix+16
  663.  
  664.            mov ax,[vmatrix+8]
  665.            imul bp
  666.            shrd ax,dx,14
  667.            mov bx,ax
  668.  
  669.            mov ax,[vmatrix+14]
  670.            imul di
  671.            shrd ax,dx,14
  672.  
  673.            add bx,ax                ; ebx = new vmatrix+28
  674.  
  675.            mov [vmatrix+8],cx
  676.            mov [vmatrix+14],bx
  677.  
  678.            mov ax,[vmatrix+10]
  679.            imul di
  680.            shrd ax,dx,14
  681.            mov cx,ax
  682.  
  683.            mov ax,[vmatrix+16]
  684.            imul si
  685.            shrd ax,dx,14
  686.  
  687.            add ecx,eax                ; ecx = new vmatrix+20
  688.  
  689.            mov ax,[vmatrix+10]
  690.            imul bp
  691.            shrd ax,dx,14
  692.            mov bx,ax
  693.  
  694.            mov ax,[vmatrix+16]
  695.            imul di
  696.            shrd ax,dx,14
  697.  
  698.            add ebx,eax                ; ebx = new vmatrix+32
  699.  
  700.            mov [vmatrix+10],cx
  701.            mov [vmatrix+16],bx
  702.  
  703.            if usez eq yes
  704.  
  705.            mov edi,ecosz              ; now perform camera z rotation,12 imuls
  706.            mov esi,esinz
  707.            mov ebp,esi
  708.            neg esi
  709.  
  710.            mov ax,[vmatrix+0]
  711.            imul di
  712.            shrd ax,dx,14
  713.            mov cx,ax
  714.  
  715.            mov ax,[vmatrix+6]
  716.            imul si
  717.            shrd ax,dx,14
  718.  
  719.            add cx,ax
  720.  
  721.            mov ax,[vmatrix+0]
  722.            imul bp
  723.            shrd ax,dx,14
  724.            mov bx,ax
  725.  
  726.            mov ax,[vmatrix+6]
  727.            imul di
  728.            shrd ax,dx,14
  729.            movsx eax,ax
  730.  
  731.            add ebx,eax
  732.  
  733.            mov [vmatrix+0],cx
  734.            mov [vmatrix+6],bx
  735.  
  736.            mov ax,[vmatrix+2]
  737.            imul di
  738.            shrd ax,dx,14
  739.            mov cx,ax
  740.  
  741.            mov ax,[vmatrix+8]
  742.            imul si
  743.            shrd ax,dx,14
  744.  
  745.            add ecx,eax
  746.  
  747.            mov ax,[vmatrix+2]
  748.            imul bp
  749.            shrd ax,dx,14
  750.            mov bx,ax
  751.  
  752.            mov ax,[vmatrix+8]
  753.            imul di
  754.            shrd ax,dx,14
  755.  
  756.            add bx,ax
  757.  
  758.            mov [vmatrix+2],cx
  759.            mov [vmatrix+8],bx
  760.  
  761.            mov ax,[vmatrix+4]
  762.            imul di
  763.            shrd ax,dx,14
  764.            mov cx,ax
  765.  
  766.            mov ax,[vmatrix+10]
  767.            imul si
  768.            shrd ax,dx,14
  769.  
  770.            add ecx,eax
  771.  
  772.            mov ax,[vmatrix+4]
  773.            imul bp
  774.            shrd ax,dx,14
  775.            mov bx,ax
  776.  
  777.            mov ax,[vmatrix+10]
  778.            imul di
  779.            shrd ax,dx,14
  780.  
  781.            add bx,ax
  782.  
  783.            mov [vmatrix+4],cx
  784.            mov [vmatrix+10],bx
  785.  
  786.            endif
  787.  
  788.            pop esi
  789.  
  790.            ret
  791.  
  792. ; generate rotation matrix for  y,x,z  camera rotation
  793. ; called only once every frame.  completed in 12 multiplys
  794. ; matrix is also used for objects with no rotation (always angle 0,0,0)
  795. ;
  796. ; where is my postcard! see readme.doc for info.
  797. ;
  798. ;              x                    y                    z
  799. ;
  800. ;x=  cz * cy + sx * sy * sz     -cx * sz     - sy * cz + sx * cy * sz
  801. ;
  802. ;y=  sz * cy - sx * sy * cz      cx * cz     - sy * sz - sz * cy * cz
  803. ;
  804. ;z=         cx * sy                 sx                cx * cy
  805. ;
  806.  
  807. ;  matrix offsets: (doublewords)
  808. ;
  809. ;     x  y  z
  810. ;
  811. ;x    0  4  8
  812. ;y   12 16 20
  813. ;z   24 28 32
  814.  
  815.            align 16
  816.  
  817. setsincose:
  818.  
  819.            mov ax,eyeax
  820.            call cosign
  821.            mov ecosx,eax          ; ecosx and such are used by object rotation
  822.            mov ax,eyeax           ; ematrix is used to find where object is
  823.            call sign
  824.            mov esinx,eax
  825.            mov [ematrix+28],eax
  826.            mov ebp,eax            ; bp = sx
  827.  
  828.            if usez eq yes
  829.            mov ax,eyeaz
  830.            call cosign
  831.            mov ecosz,eax
  832.            mov edi,eax            ; di = cz
  833.            mov ax,eyeaz
  834.            call sign
  835.            mov esinz,eax
  836.            mov edx,eax            ; dx = sz
  837.            endif
  838.  
  839.            if usez eq no
  840.            mov edi,4000h          ; di = cos 0
  841.            mov ecosz,4000h
  842.            xor edx,edx            ; dx = sin 0
  843.            mov esinz,0
  844.            endif
  845.  
  846.            mov ax,eyeay
  847.            call cosign
  848.            mov ecosy,eax
  849.            mov ax,eyeay
  850.            call sign
  851.            mov esiny,eax          ; ax = sy
  852.  
  853.            mov ebx,edx            ; save sz
  854.  
  855.            mov ecx,eax            ; save sy
  856.  
  857.            imul bx                ; bx = sy * sz
  858.            shrd ax,dx,14
  859.            movsx ebx,ax
  860.            neg ebx
  861.            mov [ematrix+20],ebx
  862.            neg ebx
  863.  
  864.            mov eax,ecx            ; si = - (cz * sy)
  865.            imul di
  866.            shrd ax,dx,14
  867.            movsx esi,ax
  868.            neg esi
  869.            mov [ematrix+8],esi
  870.  
  871.            mov eax,ecosy
  872.  
  873.            imul di                ; di = cy * cz
  874.            shrd ax,dx,14
  875.            movsx edi,ax
  876.            mov [ematrix+0],edi
  877.  
  878.            mov eax,esinz
  879.            mov ecx,ecosy
  880.  
  881.            imul cx                ; cx = sz * cy
  882.            shrd ax,dx,14
  883.            movsx ecx,ax
  884.            mov [ematrix+12],ecx
  885.  
  886.            mov eax,ebp
  887.            imul si
  888.            shrd ax,dx,14
  889.            movsx esi,ax
  890.            add [ematrix+12],esi
  891.  
  892.            mov eax,ebp
  893.            imul di
  894.            shrd ax,dx,14
  895.            movsx edi,ax
  896.            neg edi
  897.            add [ematrix+20],edi
  898.  
  899.            mov eax,ebp
  900.            imul bx
  901.            shrd ax,dx,14
  902.            movsx ebx,ax
  903.            add [ematrix+0],ebx
  904.  
  905.            mov eax,ebp
  906.            imul cx
  907.            shrd ax,dx,14
  908.            movsx ecx,ax
  909.            add [ematrix+8],ecx
  910.  
  911.            mov esi,ecosx
  912.  
  913.            mov eax,ecosy
  914.            imul si                    ; cx * cy
  915.            shrd ax,dx,14
  916.            movsx eax,ax
  917.            mov [ematrix+32],eax
  918.  
  919.            mov eax,esiny
  920.            imul si                    ; cx * sy
  921.            shrd ax,dx,14
  922.            movsx eax,ax
  923.            mov [ematrix+24],eax
  924.  
  925.            mov eax,esinz
  926.            imul si                    ;-cx * sz
  927.            shrd ax,dx,14
  928.            movsx eax,ax
  929.            neg eax
  930.            mov [ematrix+4],eax
  931.  
  932.            mov eax,ecosz
  933.            imul si                    ; cx * cz
  934.            shrd ax,dx,14
  935.            movsx eax,ax
  936.            mov [ematrix+16],eax
  937.  
  938.            neg esinx                  ; reverse angles for object rotation
  939.            neg esiny
  940.  
  941.            ret
  942.  
  943. ; generate temp matrix, 12 imul's, from object esi
  944.  
  945. ;              x                         y                      z
  946. ;
  947. ;x=  cz * cy - sx * sy * sz   - sz * cy - sx * sy * cz     - cx * sy
  948. ;
  949. ;y=         sz * cx                   cx * cz                - sx
  950. ;
  951. ;z=  cz * sy + sx * sz * cy   - sy * sz + sx * cy * cz       cx * cy
  952. ;
  953.  
  954. temp_matrix:
  955.            push esi
  956.  
  957.            mov ax,vxs[esi*2]
  958.            neg ax
  959.            push ax
  960.            call cosign
  961.            mov vcosx,ax
  962.            pop ax
  963.            call sign
  964.            mov vsinx,ax
  965.            mov ebp,eax            ; bp = sx
  966.            neg ax
  967.            mov [tmatrix+10],ax
  968.  
  969.            mov ax,vzs[esi*2]
  970.            neg ax
  971.            push ax
  972.            call cosign
  973.            mov vcosz,ax
  974.            mov edi,eax            ; di = cz
  975.            pop ax
  976.            call sign
  977.            mov vsinz,ax
  978.            mov edx,eax            ; dx = sz
  979.  
  980.            mov ax,vys[esi*2]
  981.            neg ax
  982.            push ax
  983.            call cosign
  984.            mov vcosy,ax
  985.            pop ax
  986.            call sign
  987.            mov vsiny,ax           ; ax = sy
  988.  
  989.            mov bx,dx              ; save sz
  990.  
  991.            mov cx,ax              ; save sy
  992.  
  993.            imul bx                ; bx = - sy * sz
  994.            shrd ax,dx,14
  995.            movsx ebx,ax
  996.            neg bx
  997.            mov [tmatrix+14],bx
  998.  
  999.            mov ax,cx              ; si = cz * sy
  1000.            imul di
  1001.            shrd ax,dx,14
  1002.            mov si,ax
  1003.            mov [tmatrix+12],si
  1004.  
  1005.            mov ax,vcosy
  1006.  
  1007.            imul di                ; di = cy * cz
  1008.            shrd ax,dx,14
  1009.            mov di,ax
  1010.            mov [tmatrix+0],di
  1011.  
  1012.            mov ax,vsinz
  1013.            mov cx,vcosy
  1014.  
  1015.            imul cx                ; cx = - sz * cy
  1016.            shrd ax,dx,14
  1017.            mov cx,ax
  1018.            neg cx
  1019.            mov [tmatrix+2],cx
  1020.  
  1021.            mov ax,bp
  1022.            imul si
  1023.            shrd ax,dx,14
  1024.            mov si,ax
  1025.            neg esi
  1026.            add [tmatrix+2],si
  1027.  
  1028.            mov ax,bp
  1029.            imul di
  1030.            shrd ax,dx,14
  1031.            mov di,ax
  1032.            add [tmatrix+14],di
  1033.  
  1034.            mov ax,bp
  1035.            imul bx
  1036.            shrd ax,dx,14
  1037.            mov bx,ax
  1038.            add [tmatrix+0],bx
  1039.  
  1040.            mov ax,bp
  1041.            imul cx
  1042.            shrd ax,dx,14
  1043.            mov cx,ax
  1044.            neg cx
  1045.            add [tmatrix+12],cx
  1046.  
  1047.            mov si,vcosx
  1048.  
  1049.            mov ax,vcosy
  1050.            imul si                   ; cx * cy
  1051.            shrd ax,dx,14
  1052.            mov [tmatrix+16],ax
  1053.  
  1054.            mov ax,vsiny
  1055.            imul si                   ;-cx * sy
  1056.            shrd ax,dx,14
  1057.            neg ax
  1058.            mov [tmatrix+4],ax
  1059.  
  1060.            mov ax,vsinz
  1061.            imul si                    ; cx * sz
  1062.            shrd ax,dx,14
  1063.            mov [tmatrix+6],ax
  1064.  
  1065.            mov ax,vcosz
  1066.            imul si                    ; cx * cz
  1067.            shrd ax,dx,14
  1068.            mov [tmatrix+8],ax
  1069.  
  1070.            pop esi
  1071.  
  1072.            ret
  1073.  
  1074. ; multiply tmatrix by vmatrix, [vmatrix]=[tmatrix][vmatrix]
  1075. ;
  1076. ; [ tmatrix+ 0 tmatrix+ 2 tmatrix+ 4 ] [ vmatrix+ 0 vmatrix+ 2 vmatrix+ 4 ]
  1077. ; [                                  ] [                                  ]
  1078. ; [ tmatrix+ 6 tmatrix+ 8 tmatrix+10 ] [ vmatrix+ 6 vmatrix+ 8 vmatrix+10 ]
  1079. ; [                                  ] [                                  ]
  1080. ; [ tmatrix+12 tmatrix+14 tmatrix+16 ] [ vmatrix+12 vmatrix+14 vmatrix+16 ]
  1081. ;
  1082.  
  1083. matrix_multiply:
  1084.  
  1085.            mov bx,[tmatrix+0]
  1086.            mov cx,[tmatrix+2]
  1087.            mov bp,[tmatrix+4]
  1088.  
  1089.            mov ax,[vmatrix+0]
  1090.            imul bx
  1091.            shrd ax,dx,14
  1092.            mov si,ax
  1093.  
  1094.            mov ax,[vmatrix+6]
  1095.            imul cx
  1096.            shrd ax,dx,14
  1097.            add si,ax
  1098.  
  1099.            mov ax,[vmatrix+12]
  1100.            imul bp
  1101.            shrd ax,dx,14
  1102.            add si,ax
  1103.  
  1104.            push si             ; tmatrix+0
  1105.  
  1106.            mov ax,[vmatrix+2]
  1107.            imul bx
  1108.            shrd ax,dx,14
  1109.            mov si,ax
  1110.  
  1111.            mov ax,[vmatrix+8]
  1112.            imul cx
  1113.            shrd ax,dx,14
  1114.            add si,ax
  1115.  
  1116.            mov ax,[vmatrix+14]
  1117.            imul bp
  1118.            shrd ax,dx,14
  1119.            add si,ax
  1120.  
  1121.            push si             ; tmatrix+2
  1122.  
  1123.            mov ax,[vmatrix+4]
  1124.            imul bx
  1125.            shrd ax,dx,14
  1126.            mov si,ax
  1127.  
  1128.            mov ax,[vmatrix+10]
  1129.            imul cx
  1130.            shrd ax,dx,14
  1131.            add si,ax
  1132.  
  1133.            mov ax,[vmatrix+16]
  1134.            imul bp
  1135.            shrd ax,dx,14
  1136.            add si,ax
  1137.  
  1138.            push si             ; tmatrix+4
  1139.  
  1140.            mov bx,[tmatrix+6]
  1141.            mov cx,[tmatrix+8]
  1142.            mov bp,[tmatrix+10]
  1143.  
  1144.            mov ax,[vmatrix+0]
  1145.            imul bx
  1146.            shrd ax,dx,14
  1147.            mov si,ax
  1148.  
  1149.            mov ax,[vmatrix+6]
  1150.            imul cx
  1151.            shrd ax,dx,14
  1152.            add si,ax
  1153.  
  1154.            mov ax,[vmatrix+12]
  1155.            imul bp
  1156.            shrd ax,dx,14
  1157.            add si,ax
  1158.  
  1159.            push si             ; tmatrix+6
  1160.  
  1161.            mov ax,[vmatrix+2]
  1162.            imul bx
  1163.            shrd ax,dx,14
  1164.            mov si,ax
  1165.  
  1166.            mov ax,[vmatrix+8]
  1167.            imul cx
  1168.            shrd ax,dx,14
  1169.            add si,ax
  1170.  
  1171.            mov ax,[vmatrix+14]
  1172.            imul bp
  1173.            shrd ax,dx,14
  1174.            add si,ax
  1175.  
  1176.            push si             ; tmatrix+8
  1177.  
  1178.            mov ax,[vmatrix+4]
  1179.            imul bx
  1180.            shrd ax,dx,14
  1181.            mov si,ax
  1182.  
  1183.            mov ax,[vmatrix+10]
  1184.            imul cx
  1185.            shrd ax,dx,14
  1186.            add si,ax
  1187.  
  1188.            mov ax,[vmatrix+16]
  1189.            imul bp
  1190.            shrd ax,dx,14
  1191.            add si,ax
  1192.  
  1193.            push si             ; tmatrix+10
  1194.  
  1195.            mov bx,[tmatrix+12]
  1196.            mov cx,[tmatrix+14]
  1197.            mov bp,[tmatrix+16]
  1198.  
  1199.            mov ax,[vmatrix+0]
  1200.            imul bx
  1201.            shrd ax,dx,14
  1202.            mov si,ax
  1203.  
  1204.            mov ax,[vmatrix+6]
  1205.            imul cx
  1206.            shrd ax,dx,14
  1207.            add si,ax
  1208.  
  1209.            mov ax,[vmatrix+12]
  1210.            imul bp
  1211.            shrd ax,dx,14
  1212.            add si,ax
  1213.  
  1214.            push si             ; tmatrix+12
  1215.  
  1216.            mov ax,[vmatrix+2]
  1217.            imul bx
  1218.            shrd ax,dx,14
  1219.            mov si,ax
  1220.  
  1221.            mov ax,[vmatrix+8]
  1222.            imul cx
  1223.            shrd ax,dx,14
  1224.            add si,ax
  1225.  
  1226.            mov ax,[vmatrix+14]
  1227.            imul bp
  1228.            shrd ax,dx,14
  1229.            add si,ax
  1230.  
  1231.            push si             ; tmatrix+14
  1232.  
  1233.            mov ax,[vmatrix+4]
  1234.            imul bx
  1235.            shrd ax,dx,14
  1236.            mov si,ax
  1237.  
  1238.            mov ax,[vmatrix+10]
  1239.            imul cx
  1240.            shrd ax,dx,14
  1241.            add si,ax
  1242.  
  1243.            mov ax,[vmatrix+16]
  1244.            imul bp
  1245.            shrd ax,dx,14
  1246.            add si,ax
  1247.  
  1248. ;          push si             ; tmatrix+16
  1249.  
  1250. ;          pop si
  1251.            mov [vmatrix+16],si
  1252.            pop si
  1253.            mov [vmatrix+14],si
  1254.            pop si
  1255.            mov [vmatrix+12],si
  1256.            pop si
  1257.            mov [vmatrix+10],si
  1258.            pop si
  1259.            mov [vmatrix+ 8],si
  1260.            pop si
  1261.            mov [vmatrix+ 6],si
  1262.            pop si
  1263.            mov [vmatrix+ 4],si
  1264.            pop si
  1265.            mov [vmatrix+ 2],si
  1266.            pop si
  1267.            mov [vmatrix+ 0],si
  1268.            ret
  1269.  
  1270. ;getroot:                      ; get square root of ax, where ax = 0-65535
  1271. ;           cmp ax,0fe01h      ; since ax cannot be negative anyway!
  1272. ;           jae sqr255         ; routine requires squares tables.
  1273. ;           mov si,offset squares
  1274. ;           mov cx,ax
  1275. ;           inc cx
  1276. ;           cld
  1277. ;nextroot:
  1278. ;           lodsw
  1279. ;           cmp ax,cx
  1280. ;           jbe  nextroot      ; jb is exact but jbe is better approximation
  1281. ;           mov ax,si
  1282. ;           sub ax,offset squares+3
  1283. ;           sar ax,1
  1284. ;           ret
  1285. ;sqr255:
  1286. ;           mov ax,255
  1287. ;           ret
  1288.  
  1289. ; routine courtesy TRAN
  1290. ;
  1291. ; square root
  1292. ; in:
  1293. ;   eax - number to take root of
  1294. ; out:
  1295. ;   eax - root
  1296. ;
  1297. sqrtbasetbl db 0,1,4,9,16,25,36,49,64,81,100,121,144,169,196,225
  1298.  
  1299.            public sqrt
  1300.  
  1301.            align 16
  1302.  
  1303. sqrt:
  1304.            pushad
  1305.            mov ebp,eax
  1306.            bsr ebx,eax
  1307.            jnz short sqrtf0
  1308.            xor ebx,ebx
  1309. sqrtf0:
  1310.            shr ebx,3
  1311.            lea eax,[ebx*8]
  1312.            mov cl,32
  1313.            sub cl,al
  1314.            rol ebp,cl
  1315.            mov eax,ebp
  1316.            movzx eax,al
  1317.            mov edi,offset sqrtbasetbl
  1318.            mov ecx,10h
  1319. sqrtl0:
  1320.            scasb
  1321.            je short sqrtl0d
  1322.            jb short sqrtl0d2
  1323.            loop sqrtl0
  1324.            inc edi
  1325. sqrtl0d2:
  1326.            dec edi
  1327.            inc cl
  1328. sqrtl0d:
  1329.            movzx edx,byte ptr [edi-1]
  1330.            dec cl
  1331.            xor cl,0fh
  1332.            mov edi,ecx
  1333.            mov ecx,ebx
  1334.            jecxz short sqrtdone
  1335.            sub eax,edx
  1336. sqrtml:
  1337.            shld eax,ebp,8
  1338.            rol ebp,8
  1339.            mov ebx,edi
  1340.            shl ebx,5
  1341.            xor edx,edx
  1342.            mov esi,eax
  1343.            div ebx
  1344.            rol edi,4
  1345.            add edi,eax
  1346.            add ebx,eax
  1347. sqrtf2:
  1348.            imul eax,ebx
  1349.            mov edx,eax
  1350.            mov eax,esi
  1351.            sub eax,edx
  1352.            jc short sqrtf1
  1353.            loop sqrtml
  1354. sqrtdone:
  1355.            mov [esp+28],edi
  1356.            popad
  1357.            ret
  1358. sqrtf1:
  1359.            dec ebx
  1360.            dec edi
  1361.            movzx eax,bl
  1362.            and al,1fh
  1363.            jmp sqrtf2
  1364.  
  1365. ; solve for z when x = bx (takes a point/object on a y plane and figures
  1366. ; where it would be if z = 16, y = precal7, only good for square translations)
  1367. ; uses ematrix as rotation matrix
  1368.  
  1369. ; cs set if not possible
  1370.  
  1371. ; formula is inverse of z = bx6+cx7+bp8. where precal7 is y*7
  1372. ; (16-bx(6)-precal7)/(8)=z
  1373.  
  1374.             align 16
  1375.  
  1376. precal1     dd 0
  1377. precal4     dd 0
  1378. precal7     dd 0
  1379.  
  1380. z16x:
  1381.             cmp ematrix+32,0
  1382.             je abort_attempt
  1383.  
  1384.             mov eax,ematrix+24
  1385.             imul ebx
  1386.             shrd eax,edx,14
  1387.  
  1388.             neg eax
  1389.             add eax,16
  1390.             sub eax,precal7
  1391.  
  1392.             cdq
  1393.             shld edx,eax,14
  1394.             mov ebx,ematrix+32
  1395.             idiv ebx
  1396.  
  1397.             stc
  1398.             ret
  1399. abort_attempt:
  1400.             clc
  1401.             ret
  1402.  
  1403. ; solve for x when z = bp (takes a point/object on a y plane and figures
  1404. ; where it would be if z = 16, y = precal7, only good for square translations)
  1405. ; uses ematrix as rotation matrix. output solves for z = 16
  1406.  
  1407. ; cs set if not possible
  1408.  
  1409. ; formula is inverse of z = bx6+cx7+bp8. where precal7 is y*7
  1410. ; (16-bp(8)-precal7)/(6)=x
  1411.  
  1412.             align 16
  1413.  
  1414. z16z:
  1415.             cmp ematrix+24,0
  1416.             je abort_attempt
  1417.  
  1418.             mov eax,ematrix+32
  1419.             imul ebp
  1420.             shrd eax,edx,14
  1421.  
  1422.             neg eax
  1423.             add eax,16
  1424.             sub eax,precal7
  1425.  
  1426.             cdq
  1427.             shld edx,eax,14
  1428.             mov ebx,ematrix+24
  1429.             idiv ebx
  1430.  
  1431.             stc
  1432.             ret
  1433.  
  1434. ; set precal7 for plane transformation - plane is ecx and allows above formulas
  1435. ; to determine where a point/object would be along that plane if z is negative
  1436.  
  1437. ; good for runway translations or super huge background polygons - not used
  1438. ; by regular 3d.asm routines
  1439.  
  1440. ; how to use: lets say you've got a billion background objects that are
  1441. ; on the ground (or all on the same y plane).  you call set_precal147
  1442. ; with that y plane location and use frotate instead of erotate to
  1443. ; determine where points rotated along that plane will end up.  this
  1444. ; speeds the routine up by 33% by cutting out 3 imuls.
  1445.  
  1446.             align 16
  1447.  
  1448. set_precal147:
  1449.             if usez eq yes
  1450.             mov eax,ecx
  1451.             sub eax,eyey
  1452.             imul ematrix+4
  1453.             shrd eax,edx,14
  1454.             mov precal1,eax
  1455.             endif
  1456.  
  1457.             mov eax,ecx
  1458.             sub eax,eyey
  1459.             imul ematrix+16
  1460.             shrd eax,edx,14
  1461.             mov precal4,eax
  1462.  
  1463. set_precal7:
  1464.             sub ecx,eyey
  1465.             mov eax,ecx
  1466.             imul ematrix+28
  1467.             shrd eax,edx,14
  1468.             mov precal7,eax
  1469.             ret
  1470.  
  1471.             align 16
  1472.  
  1473. ; fast object/point rotation along pre-calculated y plane
  1474.  
  1475. frotate:
  1476.            mov eax,ematrix+8
  1477.            imul ebp
  1478.            shrd eax,edx,14
  1479.            mov edi,eax
  1480.            if usez eq yes
  1481.            add edi,precal1
  1482.            endif
  1483.            mov eax,ematrix+0
  1484.            imul ebx
  1485.            shrd eax,edx,14
  1486.            add edi,eax   ; di = new x
  1487.  
  1488.            mov eax,ematrix+20
  1489.            imul ebp
  1490.            shrd eax,edx,14
  1491.            mov esi,eax
  1492.            add esi,precal4
  1493.            mov eax,ematrix+12
  1494.            imul ebx
  1495.            shrd eax,edx,14
  1496.            add esi,eax   ; si = new y
  1497.  
  1498.            mov eax,ematrix+32
  1499.            imul ebp
  1500.            shrd eax,edx,14
  1501.            mov ebp,eax
  1502.            add ebp,precal7
  1503.            mov eax,ematrix+24
  1504.            imul ebx
  1505.            shrd eax,edx,14
  1506.            add ebp,eax   ; bp = new z
  1507.  
  1508.            mov ecx,esi
  1509.            mov ebx,edi
  1510.  
  1511.            ret
  1512.  
  1513. ; fast solve for single matrix variable similar to erotate but uses frotate
  1514. ; plane matrix with precal147
  1515. ;
  1516. ; remember , matrix offsets are:
  1517. ;
  1518. ;  0 1 2     multiply those by 4 for the doublewords
  1519. ;  3 4 5
  1520. ;  6 7 8
  1521. ;
  1522.            align 16
  1523.  
  1524. fzsolve:
  1525.            mov eax,ematrix+32      ; solve z = bx(6)+cx(7)+bp(8)
  1526.            imul ebp
  1527.            shrd eax,edx,14
  1528.            mov esi,eax
  1529.            add esi,precal7
  1530.            mov eax,ematrix+24
  1531.            imul ebx
  1532.            shrd eax,edx,14
  1533.            add esi,eax   ; si = new z
  1534.            ret
  1535.  
  1536.            align 16
  1537. fxsolve:
  1538.            mov eax,ematrix+8        ; solve x = bx(0)+cx(1)+bp(2)
  1539.            imul ebp
  1540.            shrd eax,edx,14
  1541.            mov edi,eax
  1542.            if usez eq yes
  1543.            add edi,precal1
  1544.            endif
  1545.            mov eax,ematrix+0
  1546.            imul ebx
  1547.            shrd eax,edx,14
  1548.            add edi,eax   ; di = new x
  1549.            ret
  1550.  
  1551.            align 16
  1552. fysolve:
  1553.            mov eax,ematrix+20       ; solve y = bx(3)+cx(4)+bp(5)
  1554.            imul ebp
  1555.            shrd eax,edx,14
  1556.            mov ecx,eax
  1557.            add ecx,precal4
  1558.            mov eax,ematrix+12
  1559.            imul ebx
  1560.            shrd eax,edx,14
  1561.            add ecx,eax   ; cx = new y
  1562.  
  1563.            mov ebx,edi
  1564.            mov ebp,esi
  1565.  
  1566.            ret
  1567.  
  1568. ; generate lambert shading 1x3 matrix, completed in 6 imuls
  1569. ;
  1570. ;z= ( sz ( cx + ( sx * cy )) + cz * sy ) * 45degrees  [x]
  1571. ;   ( cz ( cx + ( sx * cy )) - sz * sy ) * 45degrees  [y]
  1572. ;   ( cx * cy - sx ) * 45 degrees                     [z]
  1573. ;
  1574. ;note cos45=sin45=2d41h, but we will use 2d00h (99.2% accurate)
  1575. ; you can change the y angle of the sun/light but not the x angle.
  1576. ; changing the x angle would require a new formula.
  1577. ;
  1578. lambert:
  1579.            mov ax,vxs[esi*2]
  1580.            neg ax
  1581.            push ax
  1582.            call cosign
  1583.            mov vcosx,ax
  1584.            pop ax
  1585.            call sign
  1586.            mov vsinx,ax
  1587.            mov bp,ax            ; bp = sx
  1588.  
  1589.            mov ax,vzs[esi*2]
  1590.            neg ax
  1591.            push ax
  1592.            call cosign
  1593.            mov vcosz,ax
  1594.            mov di,ax            ; di = cz
  1595.            pop ax
  1596.            call sign
  1597.            mov vsinz,ax
  1598.            mov dx,ax            ; edx = sz
  1599.  
  1600.            mov ax,vys[esi*2]
  1601.            neg ax
  1602.            add ax,y_angle_of_sun  ; 2000h = 45 degrees y angle for light source
  1603.            push ax
  1604.            call cosign
  1605.            mov vcosy,ax
  1606.            mov si,ax            ; si = cy
  1607.            pop ax
  1608.            call sign
  1609.            mov vsiny,ax          ; ax = sy
  1610.  
  1611.            mov bx,dx            ; bx = sz
  1612.  
  1613.            mov cx,ax            ; cx = sy
  1614.  
  1615.            mov ax,bp            ; get sx
  1616.  
  1617.            imul si                ; eax = sx * cy
  1618.            shrd ax,dx,14
  1619.            sub ax,vcosx          ; eax = cx + ( sx * cy)
  1620.  
  1621.            push ax
  1622.  
  1623.            imul bx                ; cx + ( sx * cy) * sz
  1624.            shrd ax,dx,14
  1625.            mov [lmatrix+0],ax
  1626.  
  1627.            pop ax
  1628.  
  1629.            imul di                ; di = cz
  1630.            shrd ax,dx,14
  1631.            mov [lmatrix+2],ax   ; cx + ( sx * cy) * cz
  1632.  
  1633.            mov ax,bx
  1634.            imul cx                ; - sz * sy
  1635.            shrd ax,dx,14
  1636.            sub [lmatrix+2],ax
  1637.  
  1638.            mov ax,di
  1639.            imul cx                ; cz * sy
  1640.            shrd ax,dx,14
  1641.            add [lmatrix+0],ax
  1642.  
  1643.            mov ax,vcosx          ; (cx * cy - sx) * 45deg
  1644.            imul si
  1645.            shrd ax,dx,14
  1646.            mov bx,ax
  1647.            add bx,bp
  1648.  
  1649.            movsx ebx,bx
  1650.            cmul eax,ebx,2d00h     ; * 45degrees
  1651.            shr eax,14
  1652.            movsx eax,ax
  1653.            mov [lmatrix+4],ax
  1654.  
  1655.            movsx ebx,[lmatrix+2]
  1656.            cmul eax,ebx,2d00h
  1657.            shr eax,14
  1658.            movsx eax,ax
  1659.            mov [lmatrix+2],ax
  1660.  
  1661.            movsx ebx,[lmatrix+0]
  1662.            cmul eax,ebx,2d00h
  1663.            shr eax,14
  1664.            mov [lmatrix+0],ax
  1665.  
  1666.            ret
  1667.  
  1668. ; pre-calculate surface normals for object edi
  1669.  
  1670. ; x2 = x2 - x1
  1671. ; y2 = y2 - y1
  1672. ; z2 = z2 - z1
  1673. ;
  1674. ; x3 = x3 - x1
  1675. ; y3 = y3 - y1
  1676. ; z3 = z3 - z1
  1677. ;
  1678. ; x = y2 * z3 - z2 * y3
  1679. ; y = z2 * x3 - x2 * z3
  1680. ; z = x2 * y3 - y2 * x3
  1681. ;
  1682. ; a = SQR(x ^ 2 + y ^ 2 + z ^ 2)
  1683. ;
  1684. ; x = INT(x / a * 256 + .5)
  1685. ; y = INT(y / a * 256 + .5)
  1686. ; z = INT(z / a * 256 + .5)
  1687.  
  1688. lx1  dd 0
  1689. ly1  dd 0
  1690. lz1  dd 0
  1691.  
  1692. lx2  dd 0
  1693. ly2  dd 0
  1694. lz2  dd 0
  1695.  
  1696. lx3  dd 0
  1697. ly3  dd 0
  1698. lz3  dd 0
  1699.  
  1700. finx dd 0
  1701. finy dd 0
  1702. finz dd 0
  1703.  
  1704. ; precalculate surface normals for object di.  this  is  so  you  don't
  1705. ; have to type them in when designing new objects. imagine, 400 points,
  1706. ; with 350 surfaces, calculating them all manually?  this routine  also
  1707. ; figures out the iteration skip offset (if you have surfaces dependant
  1708. ; on other surfaces) and also sets bit 1 if it is a line (two  points),
  1709. ; and sets bit 4 if 1 point.this routine also sets the number of points
  1710. ; to skip if an iteration is found. it  counts  the  number  of  points
  1711. ; within iterations (even iterations within iterations)  and  sets  the
  1712. ; skip value so any iterations skipped will have a pre-calculated point
  1713. ; offset.  did that make sense?
  1714. ;
  1715. ; things done here:
  1716. ;
  1717. ; set point command if only 1 connection
  1718. ; set line  command if only 2 connections
  1719. ; set normal bit in commands if shading used in texture
  1720. ; calculate and set shading normals
  1721. ; calculate offsets for iteration jumps (in case surface not visible)
  1722. ; calculate number of points to skip for iterations (in case surface not visible)
  1723. ;
  1724. ; most of the above is done so the user (you) wont have to calculate this stuff
  1725. ; yourself - makes object modification much easier.
  1726. ;
  1727. ; if you find the routine to be sloppy remember it is only used
  1728. ; for object initialization.
  1729.  
  1730. pre_cal_lambert:
  1731.            movzx edi,di           ; in case user is lazy
  1732.            mov esi,objbase[edi*4]
  1733. more_reses:
  1734.            push esi               ; save header offset
  1735.            add esi,4
  1736.            lodsd
  1737.            add esi,eax            ; handle first resolution
  1738.  
  1739.            lodsw
  1740.            mov numpoints,ax
  1741.            lodsw
  1742.            mov numsides,ax
  1743.            add esi,50             ; skip future use bytes
  1744.            mov edi,2              ; edi=2 to skip center of gravity
  1745.            mov xp,0
  1746.            mov yp,0
  1747.            mov zp,0
  1748. lam_ap12:
  1749.            mov bx,w [esi]         ; load all the points into array
  1750.            mov cx,w [esi+2]
  1751.            mov bp,w [esi+4]
  1752.            mov xp[edi],bx
  1753.            mov yp[edi],cx
  1754.            mov zp[edi],bp
  1755.            add esi,6
  1756.            add di,2
  1757.            dec numpoints
  1758.            jne s lam_ap12         ; esi = address of sides now...
  1759.  
  1760.            mov pointindex,di
  1761.  
  1762. lam_loadsides:
  1763.            mov edi,esi            ; save in case of line adjust (+16)
  1764.  
  1765.            mov ax,[esi]           ; get command
  1766.  
  1767.            mov bx,ax              ; save command
  1768.            test ax,himap          ; test if bitmap
  1769.            jz s lam_notmap        ; no, skip through loop
  1770.            add esi,8+2            ; yes, bitmap, skip 4 words + command
  1771.            jmp s lam_test_iteration ; go to next side
  1772. lam_notmap:
  1773.            mov ax,[esi+2]         ; get texture for both sides
  1774.            or  ax,[esi+4]
  1775.  
  1776.            test ax,shade          ; test shading bit
  1777.            jnz s lam_calcit       ; yes, calculate shading normal
  1778.  
  1779.            add esi,4+4+2          ; skip 2 colour & 2 texture words & command
  1780.  
  1781.            lodsw                  ; get first point indexer
  1782.            mov cx,ax
  1783.            mov dx,0
  1784. lam_ldlp:
  1785.            lodsw                  ; count number of connection points
  1786.            inc dx
  1787.            cmp ax,cx
  1788.            jne lam_ldlp
  1789.  
  1790.            cmp dx,1               ; only 1 point?, set +64
  1791.            jne lam_test_line
  1792.            or  w [edi+2],point
  1793.            or  w [edi+4],point
  1794.            jmp lam_test_iteration
  1795.  
  1796. lam_test_line:
  1797.            cmp dx,2               ; only 2 points?, set +16
  1798.            jne lam_test_iteration
  1799.            or  w [edi+2],line
  1800.            or  w [edi+4],line
  1801.  
  1802. lam_test_iteration:
  1803.            test bx,iterate        ; test if iteration command used
  1804.            jnz lam_do_it          ; yes,solve internal iteration
  1805. lam_next:
  1806.            dec numsides
  1807.            jnz lam_loadsides
  1808.  
  1809.            pop esi
  1810.            lodsd
  1811.            add esi,4
  1812.            cmp eax,-1             ; last resolution?
  1813.            jne more_reses
  1814.  
  1815.            ret
  1816.  
  1817. lam_calcit:
  1818.            push esi               ; save command location
  1819.            add esi,4+4+2          ; skip colour and 2 future use words
  1820.  
  1821.            lodsw                  ; first point
  1822.            push ax
  1823.            movzx edi,ax
  1824.            shl edi,1
  1825.  
  1826.            movsx ebx,[xp+edi]
  1827.            movsx ecx,[yp+edi]
  1828.            movsx ebp,[zp+edi]
  1829.  
  1830.            mov lx1,ebx
  1831.            mov ly1,ecx
  1832.            mov lz1,ebp
  1833.  
  1834.            lodsw                  ; second point
  1835.            movzx edi,ax
  1836.            shl edi,1
  1837.  
  1838.            movsx ebx,[xp+edi]
  1839.            movsx ecx,[yp+edi]
  1840.            movsx ebp,[zp+edi]
  1841.  
  1842.            mov lx2,ebx
  1843.            mov ly2,ecx
  1844.            mov lz2,ebp
  1845.  
  1846.            lodsw                  ; third point
  1847.            movzx edi,ax
  1848.            shl edi,1
  1849.  
  1850.            movsx ebx,[xp+edi]
  1851.            movsx ecx,[yp+edi]
  1852.            movsx ebp,[zp+edi]
  1853.  
  1854.            mov lx3,ebx
  1855.            mov ly3,ecx
  1856.            mov lz3,ebp
  1857.  
  1858.            push esi
  1859.  
  1860.            call calc_normal
  1861.  
  1862.            pop esi
  1863.  
  1864.            pop dx                 ; now find shading normal storage, pop first connector
  1865.  
  1866. lam_ldl2:
  1867.            lodsw
  1868.            cmp ax,dx
  1869.            jne lam_ldl2
  1870.  
  1871.            mov edi,esi
  1872.  
  1873.            mov ax,bx
  1874.            stosw
  1875.            mov ax,cx
  1876.            stosw
  1877.            mov ax,bp
  1878.            stosw
  1879.  
  1880.            add esi,6
  1881.  
  1882.            pop edi         ; get original command location back
  1883.            or w [edi],normal
  1884.            mov bx,[edi]
  1885.            jmp lam_test_iteration
  1886.  
  1887. lam_surfc_cnt dw 0
  1888.  
  1889. ; this finds the total number of points to skip if an iteration fails, dx = #
  1890. ; remember, this is a pre-calculation routine so it doesn't need to be fast.
  1891.  
  1892. lam_do_it:
  1893.            mov lam_surfc_cnt,0
  1894.            mov dx,0
  1895.            push esi        ; this is our return address (continue from here+4)
  1896.  
  1897.            lodsw           ; get number of points.
  1898.            add dx,ax       ; save as TOTAL number of points to skip
  1899.            mov numpoints,ax
  1900.  
  1901.            lodsw           ; get number of surfaces
  1902.            add lam_surfc_cnt,ax ; count until this is zero
  1903.            add esi,25*2
  1904.  
  1905.            movzx edi,pointindex
  1906.            cmp numpoints,0
  1907.            je lam_test_check        ; only sides added, no additional points
  1908. lam_ap13:
  1909.            mov bx,w [esi]         ; load all the points into array
  1910.            mov cx,w [esi+2]       ; for calculation of gourad shadings
  1911.            mov bp,w [esi+4]
  1912.            mov xp[edi],bx
  1913.            mov yp[edi],cx
  1914.            mov zp[edi],bp
  1915.            add esi,6
  1916.            add di,2
  1917.            dec numpoints
  1918.            jne s lam_ap13         ; esi = address of sides now...
  1919.  
  1920.            mov pointindex,di
  1921.  
  1922. lam_test_check:
  1923.            cmp lam_surfc_cnt,0    ; test if user just wants to add points
  1924.            je lam_no_surfs        ; i dont know why anyone would want to do this?
  1925.  
  1926. lam_test_until_target:
  1927.            lodsw                  ; get command
  1928.            mov bx,ax
  1929.            test ax,himap          ; test if bitmap
  1930.            jz s lam_notmap_it     ; no, skip through loop
  1931.            add esi,8              ; yes, bitmap, skip 4 words
  1932.            jmp s lam_nog
  1933.  
  1934. lam_notmap_it:
  1935.            lodsw
  1936.            mov bp,ax
  1937.            lodsw
  1938.            or bp,ax               ; find if shading bit used, add esi,6 if so
  1939.            add esi,4              ; skip 2 colour words
  1940.  
  1941.            lodsw                  ; get first point indexer
  1942.            mov cx,ax
  1943. lam_ldl3:
  1944.            lodsw
  1945.            cmp ax,cx
  1946.            jne lam_ldl3
  1947.  
  1948.            test bp,shade          ; test if gouraud normal present
  1949.            jz lam_nog
  1950.            add esi,6              ; skip it if present
  1951. lam_nog:
  1952.            test bx,iterate        ; test if iteration command used
  1953.            jnz lam_re_lam         ; solve internal iteration again...
  1954. lam_next_it:
  1955.            dec lam_surfc_cnt
  1956.            jnz lam_test_until_target
  1957. lam_no_surfs:
  1958.            mov edi,esi            ; save current location
  1959.            pop esi                ; return original start location
  1960.            sub edi,esi            ; get difference between them
  1961.            sub di,8
  1962.  
  1963.            lodsw                  ; get number of points
  1964.            mov bx,ax
  1965.  
  1966.            lodsw
  1967.            add numsides,ax
  1968.  
  1969.            mov cx,dx
  1970.            mov ax,6
  1971.            imul bx
  1972.            movzx ebx,ax
  1973.  
  1974.            mov ax,di
  1975.            mov edi,esi
  1976.            stosw                  ; save offset
  1977.            mov ax,cx
  1978.            stosw                  ; save number of points found in iterations
  1979.  
  1980.            add esi,25*2           ; adjust for next load
  1981.            add esi,ebx
  1982.  
  1983.            jmp lam_next
  1984.  
  1985. lam_re_lam:
  1986.            lodsw           ; get number of points for recursed iteration
  1987.            add dx,ax       ; save as TOTAL number of points to skip
  1988.            mov cx,ax
  1989.  
  1990.            lodsw           ; get number of surfaces
  1991.            add lam_surfc_cnt,ax ; count until this is zero
  1992.            add esi,25*2
  1993.  
  1994.            mov eax,6
  1995.            imul cx
  1996.            add esi,eax
  1997.  
  1998.            jmp lam_next_it
  1999.  
  2000. ; calculate surface normal given points l1,l2,l3.  result is
  2001. ; vector in ebx,ecx,ebp.  this worked for me on the first try!
  2002.  
  2003. calc_normal:
  2004.            mov ebx,lx1
  2005.            mov ecx,ly1
  2006.            mov ebp,lz1
  2007.  
  2008.            sub lx2,ebx
  2009.            sub ly2,ecx
  2010.            sub lz2,ebp
  2011.  
  2012.            sub lx3,ebx
  2013.            sub ly3,ecx
  2014.            sub lz3,ebp
  2015.  
  2016.            mov eax,ly2
  2017.            mov ebx,lz3
  2018.            imul ebx
  2019.            mov ecx,eax
  2020.  
  2021.            mov eax,lz2
  2022.            mov ebx,ly3
  2023.            imul ebx
  2024.            sub ecx,eax
  2025.  
  2026.            mov finx,ecx ; save x of normal
  2027.  
  2028.            mov eax,lz2
  2029.            mov ebx,lx3
  2030.            imul ebx
  2031.            mov ecx,eax
  2032.  
  2033.            mov eax,lx2
  2034.            mov ebx,lz3
  2035.            imul ebx
  2036.            sub ecx,eax
  2037.  
  2038.            mov finy,ecx ; save y of normal
  2039.  
  2040.            mov eax,lx2
  2041.            mov ebx,ly3
  2042.            imul ebx
  2043.            mov ecx,eax
  2044.  
  2045.            mov eax,ly2
  2046.            mov ebx,lx3
  2047.            imul ebx
  2048.            sub ecx,eax
  2049.  
  2050.            mov finz,ecx ; save z of normal
  2051.  
  2052. calc_testloop:
  2053.            cmp finx,32768 ; make sure (normal^2)*2 is < 2^32
  2054.            jge calc_shrit
  2055.            cmp finz,32768
  2056.            jge calc_shrit
  2057.            cmp finz,32768
  2058.            jge calc_shrit
  2059.  
  2060.            cmp finx,-32768
  2061.            jle calc_shrit
  2062.            cmp finz,-32768
  2063.            jle calc_shrit
  2064.            cmp finz,-32768
  2065.            jg  ok_2_bite_dust
  2066.  
  2067. calc_shrit:
  2068.            shr finx,1   ; calculations will be too large if squared, div by 2
  2069.            test finx,40000000h
  2070.            jz no_neg_calc1
  2071.            or   finx,80000000h
  2072. no_neg_calc1:
  2073.            shr finy,1
  2074.            test finy,40000000h
  2075.            jz no_neg_calc2
  2076.            or   finy,80000000h
  2077. no_neg_calc2:
  2078.            shr finz,1
  2079.            test finz,40000000h
  2080.            jz no_neg_calc3
  2081.            or   finz,80000000h
  2082. no_neg_calc3:
  2083.            jmp calc_testloop
  2084.  
  2085. ok_2_bite_dust:
  2086.            mov eax,finx ; x^2
  2087.            mov edi,eax  ; objects
  2088.            imul edi
  2089.            mov edi,eax
  2090.  
  2091.            mov eax,finy ; y^2
  2092.            mov esi,eax
  2093.            imul esi
  2094.            mov esi,eax
  2095.  
  2096.            mov eax,finz ; z^2
  2097.            mov ebp,eax
  2098.            imul ebp
  2099.  
  2100.            add eax,esi
  2101.            add eax,edi
  2102.  
  2103.            call sqrt    ; get square root of number
  2104.  
  2105.            mov ecx,eax
  2106.            cmp ecx,0
  2107.            je lam_abort ; should never happen!
  2108.  
  2109.            mov eax,finx
  2110.            cdq
  2111.            shl eax,8    ; set unit vector to 256
  2112.            idiv ecx
  2113.            mov finx,eax
  2114.  
  2115.            mov eax,finy
  2116.            cdq
  2117.            shl eax,8
  2118.            idiv ecx
  2119.            mov finy,eax
  2120.  
  2121.            mov eax,finz
  2122.            cdq
  2123.            shl eax,8
  2124.            idiv ecx
  2125.            mov finz,eax
  2126.  
  2127.            mov ebx,finx
  2128.            mov ecx,finy
  2129.            mov ebp,finz
  2130.  
  2131. lam_abort:
  2132.            ret
  2133.  
  2134. ; set up all lambert normals from object si to object di
  2135.  
  2136. set_up_all_lambert:
  2137.            movzx edi,di ; in case user is lazy
  2138.            movzx esi,si
  2139.  
  2140.            xchg edi,esi
  2141. set_lop:
  2142.            push esi edi
  2143.            call pre_cal_lambert
  2144.            pop edi esi
  2145.            inc edi
  2146.            cmp edi,esi
  2147.            jb  set_lop
  2148.  
  2149.            ret
  2150.  
  2151. ; rotate surface normal through lambert matrix
  2152.  
  2153. lrotate:
  2154.            mov ax,w lmatrix+4    ; solve edi = bx(0)+cx(4)+bp(8)
  2155.            imul bp
  2156.            shrd ax,dx,14
  2157.            movsx edi,ax
  2158.            mov ax,w lmatrix+2
  2159.            imul cx
  2160.            shrd ax,dx,14
  2161.            movsx eax,ax
  2162.            add edi,eax
  2163.            mov ax,w lmatrix+0
  2164.            imul bx
  2165.            shrd ax,dx,14
  2166.            movsx eax,ax
  2167.            add edi,eax          ; di = new colour 0=255
  2168.  
  2169.            ret
  2170.  
  2171. ; fast pathagorean solve, sqr(ax^2+bx^2) works well for numbers ax<90, bx<128
  2172. ; uses huge table.  limit of solve is for 16 bit values:eg sqr(65535^2+65535^2)
  2173.  
  2174. pathagorean:
  2175. ;          include pathagor.inc ; dont include this routine if you don't need it
  2176.                                 ; 'cause it's a real big table.
  2177. sqrax2bx2:
  2178.            cmp ax,bx            ; set ax = smallest
  2179.            ja s pa_smal
  2180.            xchg ax,bx
  2181. pa_smal:
  2182.            cmp ax,90            ; check if parameters of triangle are within
  2183.            jae s pa_imul        ; table or are too big for fast load.
  2184.            cmp bx,128
  2185.            jae s pa_imul
  2186.  
  2187.            shl bx,7             ; *128
  2188.            add ax,bx            ; ax = bx*128+ax
  2189.            movzx esi,ax
  2190.            xor eax,eax
  2191.            mov al,b pathagorean[esi]
  2192.            ret
  2193. pa_imul:
  2194.            movzx eax,ax         ; variables too large, do mathematically
  2195.            movzx ebx,bx
  2196.            imul eax,eax
  2197.            imul ebx,ebx
  2198.            add eax,ebx
  2199.            jmp sqrt
  2200.  
  2201.